package com.example.service.impl;

import com.alibaba.fastjson.JSON;
import com.example.domain.FruitClean;
import com.example.domain.UserProgress;
import com.example.mapper.FruitCleanMapper;
import com.example.mapper.UserProgressMapper;
import com.example.service.FruitCleanService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class FruitCleanServiceImpl implements FruitCleanService {
    @Autowired
    private FruitCleanMapper fruitCleanMapper;
    @Autowired
    private UserProgressMapper userProgressMapper;
    private final Random random = new Random();
    private final String[] initFruitArr = {"B","H","V","S"};

    /**
     * 生成水果
     * @param level
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String generatorGate(Integer level) {
        //sessionid
        String sessionid=UUID.randomUUID().toString().replaceAll("-","");
        String[][] fruitArr=null;
        // 1. 数据库查找是否已生成对应关卡
        FruitClean fruitClean = fruitCleanMapper.selectByGateNum(level);
        if (Objects.nonNull(fruitClean)) {
            fruitArr = JSON.parseObject(fruitClean.getFruitArray(), String[][].class);

        }else{
            fruitArr = new String[8][8];
            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {
                    fruitArr[i][j]=produceFruit();
                }
            }
            //生成对应关卡
            fruitClean=new FruitClean();
            fruitClean.setGateNumber(level);
            fruitClean.setFruitArray(JSON.toJSONString(fruitArr));
            fruitCleanMapper.insert(fruitClean);
        }
        //生成用户记录
        UserProgress progress=new UserProgress();
        progress.setSessionId(sessionid);
        progress.setFruitArray(JSON.toJSONString(fruitArr));
        userProgressMapper.insert(progress);
        return sessionid+System.getProperty("line.separator")+getProcessStr(fruitArr);
    }

    /**
     * 移除
     * @param sessionId 用户id
     * @param row0 左上角 row
     * @param col0 左上角 col
     * @param row1 右下角 row
     * @param col1 右下角 col
     * @return
     */
    public String move(String sessionId, Integer row0, Integer col0, Integer row1, Integer col1) {
        UserProgress progress=userProgressMapper.selectBySessionId(sessionId);
        if(progress==null)
            return "INVALID PARAMS";
        String[][] fruitArr = JSON.parseObject(progress.getFruitArray(), String[][].class);
        Set<String> hasClean = new HashSet<>();
        //清理格子
        for (int i = row0; i <= row1; i++) {
            for (int j = col0; j <= col1; j++) {
                doClean(i,j,fruitArr,hasClean);
            }
        }
        //补充数据
        fillFruitArr(fruitArr);
        //保存用户进度
        progress.setFruitArray(JSON.toJSONString(fruitArr));
        userProgressMapper.update(progress);
        return getProcessStr(fruitArr);
    }


    private void doClean(int row, int col, String[][] progress, Set<String> hasClean){
        if(hasClean.add(row+","+col)){//记录处理节点，防止死循环
            String furit=progress[row][col];
            //生产新水果
            progress[row][col]=Strings.EMPTY;
            if("B".equals(furit)){
                //无需处理
            }else if("H".equals(furit)){//横向消除
                //所在行全部消除
                for (int i = 0; i < progress[row].length; i++) {
                    doClean(row,i,progress,hasClean);
                }
            }else if("V".equals(furit)){//纵向消除
                for (int i = 0; i < progress.length; i++) {
                    doClean(i,col,progress,hasClean);
                }
            }else if("S".equals(furit)){//四周消除
                for (int r = row-1; r <= row + 1; r++) {
                    if(r<0||r>=progress.length)
                        continue;
                    for (int c = col-1; c <= col + 1; c++) {
                        if(c<0||c>=progress[0].length)
                            continue;
                        doClean(r,c,progress,hasClean);
                    }
                }
            }
        }
    }
    /**
     * 填充空数据
     * @param fruitArr
     */
    private void fillFruitArr(String[][] fruitArr) {
        for (int i = fruitArr.length-1; i >= 0; i--) {//从最后一行开始
            for (int j = 0; j < fruitArr[0].length; j++) {
                if(Strings.isEmpty(fruitArr[i][j])){//水果已消除，需要填充
                    //依次向上找，找到后下落，如果没有，重新生成
                    for (int r = i-1; r >= 0; r--) {
                        if(Strings.isNotEmpty(fruitArr[r][j])){
                            //下落
                            fruitArr[i][j]=fruitArr[r][j];
                            //清空已下落数据
                            fruitArr[r][j]=Strings.EMPTY;
                            break;
                        }
                    }
                    //如果当前依然未空，重新生成
                    if(Strings.isEmpty(fruitArr[i][j])){
                        fruitArr[i][j]=produceFruit();
                    }
                }
            }
        }
    }
    /**
     * 生成进度字符串
     * @param process 进度数组
     * @return 数组字符串
     */
    private String getProcessStr(String[][] process){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < process.length; i++) {
            for (int j = 0; j < process[i].length; j++) {
                sb.append(process[i][j]);
            }
            sb.append(System.getProperty("line.separator"));
        }
        return sb.toString();
    }
    /**
     * 生成随机水果
     * @return 水果
     */
    private String produceFruit(){
        return initFruitArr[random.nextInt(4)];
    }
}
